package controller

import (
	"app-webapi/comm"
	g "app-webapi/comm/g"
	"app-webapi/comm/response"
	"app-webapi/entity"
	"app-webapi/entity/dto"
	"app-webapi/service"
	"github.com/gin-gonic/gin"
	"github.com/google/uuid"
	"net/http"
	"time"
)

// Login 登录
func Login(c *gin.Context) {
	// 验证码校验
	loginDto := dto.LoginDto{}
	if err := c.ShouldBindJSON(&loginDto); err != nil {
		response.Err(g.ParamInvalid, err.Error(), c)
		return
	}

	if !comm.VerifyCaptcha(loginDto.CaptchaId, loginDto.Captcha) {
		response.Err(g.ParamInvalid, "验证码错误", c)
		return
	}

	var user entity.Userinfo
	g.Db.Where(&entity.Userinfo{Username: loginDto.Username}).First(&user)

	// 检查 ErrRecordNotFound 错误
	if user.ID == 0 {
		response.Err(g.ParamInvalid, "用户名或密码错误", c)
		return
	}

	// 检查密码
	if !comm.BcryptVerify(loginDto.Password, user.Password) {
		response.Err(g.ParamInvalid, "用户名或密码错误", c)
		return
	}
	//校验用户过期时间 到期时间小于现在24小时
	if !user.ExpireDate.IsZero() && user.ExpireDate.Add(24*time.Hour).Before(time.Now()) {
		response.Err(g.ParamInvalid, "用户已过期", c)
		return
	}

	// token
	newUUID, _ := uuid.NewUUID()
	token := newUUID.String()
	//保存token
	user.Token = token
	g.Db.Updates(&user)

	c.Set("user", &user)
	// 添加登录记录
	service.GenerateLog(c, entity.LoginOperation, "登录系统")

	response.Success("登录成功", map[string]any{"token": token}, c)
	return

}

// GetUserinfo 个人信息查询
func GetUserinfo(c *gin.Context) {

	username := c.Query("username")
	if username == "" {
		c.JSON(http.StatusInternalServerError, g.JsonResult{
			Message:    "用户名参数为空",
			StatusCode: http.StatusInternalServerError,
		})
		return
	}

	userinfo := service.GetUserinfo(username)

	c.JSON(http.StatusOK, g.JsonResult{
		Message:    "获取成功",
		StatusCode: http.StatusOK,
		Data:       userinfo,
	})
	return
}

type ModifyUserInfoReq struct {
	ID       uint   `json:"id"`
	Username string `json:"username"`
	RealName string `json:"realName"`
	Dept     string `json:"dept"`
	Position string `json:"position"`
	Tel      string `json:"tel"`
	Role     string `json:"role"`
}

func ModifyUserInfo(c *gin.Context) {
	req := ModifyUserInfoReq{}
	if err := c.ShouldBindJSON(&req); err != nil {
		response.Err(g.ParamInvalid, err.Error(), c)
		return
	}
	userinfo := c.MustGet("user").(*entity.Userinfo)
	if userinfo.ID != req.ID {
		response.Err(g.ParamInvalid, "登录用户ID与修改ID不一致", c)
		return
	}
	userDb := &entity.Userinfo{}
	// 校验用户名是否存在
	g.Db.Model(userDb).Where("username = ?", req.Username).Not("id = ?", req.ID).First(userDb)
	if userDb.ID > 0 {
		response.Err(g.ParamInvalid, "用户名已存在", c)
		return
	}
	userDb = &entity.Userinfo{}
	//更新用户
	g.Db.Model(userDb).Where("id = ?", req.ID).Updates(&req)
	response.Success(g.Updated, nil, c)
	// 添加记录
	service.GenerateLog(c, entity.UpdateOperation, "修改个人信息")
	return
}

// ModifyPassword 登录密码修改
func ModifyPassword(c *gin.Context) {
	req := dto.ModifyPasswordDto{}
	if err := c.ShouldBindJSON(&req); err != nil {
		response.Err(g.ParamInvalid, err.Error(), c)
		return
	}

	currentUser := c.MustGet("user").(*entity.Userinfo)
	if req.ID != currentUser.ID {
		if !currentUser.IsSuperAdmin && currentUser.Role != "admin" {
			response.Err(g.ParamInvalid, "非当前用户 非管理员 不能修改密码", c)
			return
		}
	}

	// 用户ID校验
	if req.ID == 0 {
		response.Err(g.ParamInvalid, "用户ID不能为空", c)
		return
	}

	user := entity.Userinfo{}
	g.Db.Model(&user).First(&user, req.ID)

	if user.Username == "@1Q2W3E4R5T%" {
		response.Err(g.ParamInvalid, "超级管理员密码不能修改", c)
		return
	}

	if user.ID == 0 {
		response.Err(g.ParamInvalid, "用户不存在", c)
		return
	}

	if req.Password != req.ConfirmPassword {
		response.Err(g.ParamInvalid, "两次密码不一致", c)
		return
	}

	if comm.BcryptVerify(req.Password, user.Password) {
		response.Err(g.ParamInvalid, "新密码与旧密码相同", c)
		return
	}

	user.Password = comm.BCrypt(req.Password)
	g.Db.Model(user).Updates(user)
	//清除用户Token
	g.Db.Model(user).Where("id = ?", user.ID).Update("token", "")
	// 添加记录
	service.GenerateLog(c, entity.UpdateOperation, "修改密码")
	response.Success(g.Updated, nil, c)

}

// LoginOut 退出登录
func LoginOut(c *gin.Context) {
	currentUser := c.MustGet("user").(*entity.Userinfo)
	if currentUser == nil {
		response.Err(g.ParamInvalid, "用户不存在", c)
		return
	}

	g.Db.Model(&entity.Userinfo{}).Where("id = ?", currentUser.ID).Update("token", "")
	// 添加记录
	service.GenerateLog(c, entity.LogoutOperation, "退出系统")
	response.Success(g.Updated, nil, c)
	return
}

// AddUser 新增用户
func AddUser(c *gin.Context) {
	req := entity.Userinfo{}
	if err := c.ShouldBindJSON(&req); err != nil {
		response.Err(g.ParamInvalid, err.Error(), c)
		return
	}

	currentUser := c.MustGet("user").(*entity.Userinfo)
	if !currentUser.IsSuperAdmin && currentUser.Role != "admin" {
		response.Err(g.ParamInvalid, "非管理员禁止新增", c)
		return
	}

	// 校验是否超级管理员
	if req.IsSuperAdmin {
		response.Err(g.ParamInvalid, "不能新增超级管理员", c)
		return
	}
	// 校验用户名是否存在
	g.Db.Where("username = ?", req.Username).First(&req)
	if req.ID > 0 {
		response.Err(g.ParamInvalid, "用户名已存在", c)
		return
	}
	// 校验有效期是否早于当天
	if req.ExpireDate.Before(time.Now()) {
		response.Err(g.ParamInvalid, "有效期不能早于当天", c)
		return
	}
	//密码空校验
	if req.PasswordForReq == "" {
		response.Err(g.ParamInvalid, "密码不能为空", c)
		return
	}

	// 密码BCrypt加盐
	req.Password = comm.BCrypt(req.PasswordForReq)
	req.CreateUserId = currentUser.ID

	g.Db.Create(&req)

	// 添加记录
	service.GenerateLog(c, entity.CreateOperation, "新增用户\""+req.Username+"\"")
	response.Success(g.Created, nil, c)
	return
}

// UpdateUserinfo 修改用户信息
func UpdateUserinfo(c *gin.Context) {
	req := entity.Userinfo{}
	if err := c.ShouldBindJSON(&req); err != nil {
		response.Err(g.ParamInvalid, err.Error(), c)
		return
	}
	if req.ID <= 0 {
		response.Err(g.ParamInvalid, "用户ID不能为空", c)
		return
	}

	currentUser := c.MustGet("user").(*entity.Userinfo)
	if !currentUser.IsSuperAdmin && currentUser.Role != "admin" {
		response.Err(g.ParamInvalid, "非管理员禁止修改", c)
		return
	}

	//根据ID查询用户
	userDb := &entity.Userinfo{}
	g.Db.First(userDb, req.ID)
	if userDb.ID == 0 {
		response.Err(g.ParamInvalid, "用户不存在", c)
		return
	}
	if userDb.IsSuperAdmin != req.IsSuperAdmin {
		response.Err(g.ParamInvalid, "不能修改是否超级管理员", c)
		return
	}
	if userDb.Username == "@1Q2W3E4R5T%" {
		response.Err(g.ParamInvalid, "不能修改内置超级管理员", c)
		return
	}
	if userDb.Username == "admin" && req.Username != "admin" {
		response.Err(g.ParamInvalid, "不能修改admin的用户名", c)
		return
	}
	// 校验有效期是否早于当天
	if req.ExpireDate.Before(time.Now()) {
		response.Err(g.ParamInvalid, "有效期不能早于当天", c)
		return
	}

	userDb2 := &entity.Userinfo{}
	// 校验用户名是否存在
	g.Db.Model(userDb2).Where("username = ?", req.Username).Not("id = ?", req.ID).First(userDb2)
	if userDb2.ID > 0 {
		response.Err(g.ParamInvalid, "用户名已存在", c)
		return
	}

	if len(req.PasswordForReq) != 0 {
		// 密码BCrypt加盐
		req.Password = comm.BCrypt(req.PasswordForReq)
	}

	// 更新用户信息
	g.Db.Model(&req).Updates(req)
	// 添加记录
	service.GenerateLog(c, entity.UpdateOperation, "修改用户\""+req.Username+"\"")
	response.Success(g.Updated, nil, c)

}

// DeleteUser 删除用户
func DeleteUser(c *gin.Context) {
	id := c.Param("id")
	if id == "" {
		response.Err(g.ParamInvalid, "用户ID不能为空", c)
		return
	}

	currentUser := c.MustGet("user").(*entity.Userinfo)
	if !currentUser.IsSuperAdmin {
		response.Err(g.ParamInvalid, "非超级管理员禁止删除", c)
		return
	}

	req := entity.Userinfo{}
	g.Db.Where("id = ?", id).First(&req)
	if req.IsSuperAdmin {
		response.Err(g.ParamInvalid, "不能删除超级管理员", c)
		return
	}

	g.Db.Where("id = ?", id).Delete(&entity.Userinfo{})
	// 添加记录
	service.GenerateLog(c, entity.DeleteOperation, "删除用户\""+req.Username+"\"")
	response.Success(g.Deleted, nil, c)

}

type GetUserListReq struct {
	//可以根据 用户名、真实姓名、联系方式、过期时间范围查询
	Username string `form:"username" json:"username"`
	RealName string `form:"realName" json:"realName"`
	Tel      string `form:"tel" json:"tel"`
	comm.TimeReq
	comm.Page
}

// GetUserList 获取用户列表
func GetUserList(c *gin.Context) {
	//可以根据 用户名、真实姓名、联系方式、过期时间范围查询
	req := GetUserListReq{}
	if err := c.ShouldBindQuery(&req); err != nil {
		response.Err(g.ParamInvalid, err.Error(), c)
		return
	}

	tx := g.Db.Model(&entity.Userinfo{}).Where("username != '@1Q2W3E4R5T%' and username like ? and real_name like ? and tel like ? ", "%"+req.Username+"%", "%"+req.RealName+"%", "%"+req.Tel+"%")
	// 时间查询
	if !req.FromTime.IsZero() && !req.ToTime.IsZero() {
		tx.Where("expire_date between ? and ?", req.FromTime, req.ToTime)
	}
	// 分页查询
	var total int64
	tx.Count(&total)
	var list []entity.Userinfo
	tx.Scopes(comm.Paginate(req.Page)).Preload("CreateUser").Find(&list)
	for i, _ := range list {
		if list[i].CreateUser != nil {
			list[i].CreateUserName = list[i].CreateUser.RealName
		}
	}
	response.SuccessPage(g.Selected, list, total, c)
}

// GetUserDetail 获取用户详情
func GetUserDetail(c *gin.Context) {
	id := c.Param("id")
	if id == "" {
		response.Err(g.ParamInvalid, "用户ID不能为空", c)
		return
	}
	userinfo := entity.Userinfo{}
	g.Db.Where("id = ?", id).Preload("CreateUser").First(&userinfo)
	if userinfo.CreateUser != nil {
		userinfo.CreateUserName = userinfo.CreateUser.RealName
	}
	response.Success(g.Selected, userinfo, c)

}
